package com.agger.harmonyosthemeseditor.intelligent;

import com.agger.harmonyosthemeseditor.userinterface.GeneralToast;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.ai.cv.common.*;
import ohos.ai.cv.sr.IImageSuperResolution;
import ohos.ai.cv.sr.SisrConfiguration;
import ohos.app.Context;
import ohos.data.rdb.ValuesBucket;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.*;
import ohos.media.photokit.metadata.AVStorage;
import ohos.utils.net.Uri;

import java.io.*;

public class ImageIntelligent
{

    static int result=-1001;
    static PixelMap pixelMap;
    static VisionImage image;
    static IImageSuperResolution imageSuperResolution;
    static ImageResult imageResult;
    public static boolean ConnectSuccess = false;

    private static ConnectionCallback connectionCallback(VisionImage image, boolean SCALE_3X)
    {
        return new ConnectionCallback()
        {
            @Override
            public void onServiceConnect()
            {
                if(!ConnectSuccess) {ConnectSuccess = true;}
                else
                {
                    if(SCALE_3X)
                    {
                        imageResult = new ImageResult();
                        SisrConfiguration.Builder builder = new SisrConfiguration.Builder();
                        builder.setProcessMode(VisionConfiguration.MODE_IN);
                        SisrConfiguration config = builder.build();
                        config.setScale(SisrConfiguration.SISR_SCALE_3X);
                        config.setQuality(SisrConfiguration.SISR_QUALITY_HIGH);
                        imageSuperResolution.setVisionConfiguration(config);
                        result = imageSuperResolution.doSuperResolution(image, imageResult, null);
                    }else
                    {
                        imageResult = new ImageResult();
                        SisrConfiguration.Builder builder = new SisrConfiguration.Builder();
                        builder.setProcessMode(VisionConfiguration.MODE_IN);
                        SisrConfiguration config = builder.build();
                        config.setScale(SisrConfiguration.SISR_SCALE_1X);
                        config.setQuality(SisrConfiguration.SISR_QUALITY_HIGH);
                        imageSuperResolution.setVisionConfiguration(config);
                        result = imageSuperResolution.doSuperResolution(image, imageResult, null);
                    }
                }
            }

            @Override
            public void onServiceDisconnect()
            {
                // 定义连接能力引擎失败后的操作。
            }
        };
    }

    public static void Init(Context context)
    {
        imageSuperResolution = VisionManager.getSisr(context);
        ConnectionCallback connectionCallback = connectionCallback(image,false);
        VisionManager.init(context, connectionCallback);
    }

    public static PixelMap EnhanceImage(PixelMap pxm,Context context,boolean SCALE_3X)
    {
        imageSuperResolution = VisionManager.getSisr(context);
        pixelMap = pxm;
        image = VisionImage.fromPixelMap(pixelMap);
        // 定义连接回调，实现连接能力引擎成功与否后的操作
        ConnectionCallback connectionCallback = connectionCallback(image,SCALE_3X);
        // 建立与能力引擎的连接
        VisionManager.init(context, connectionCallback);
        if(result==0)
        {
            return imageResult.getPixelMap();
        }else
        {
            return pxm;
        }
    }

    //本方法可智慧型裁剪图象的无意义边框，主要用于优化全面屏设备，在截图传统十六比九或四比三画面后留下的空白边距
    //如果检查到边框为零，将执行新一轮的分析，根据色块的复杂度来计算图象目标区域
    //为避免智慧意识过渡依赖大数据，并催生过多的智慧能力训练师产业，造成生物特征体反向给智慧意识服务的物体
    //根据爱洁羊体系智慧能力规范要求，不得随意使用训练师来建立智慧模型库，程式必须寻求全新的【元智慧】算法来实现同等智能，基于大数据和有机生命体训练的智慧模型将永远无法反超生物文明
    //爱洁羊图象智慧能力正式版不会使用英文编码，预计以晓萌光标准算法语言发行，晓萌光标准算法语言（ㄓㄨㄧㄣㄔㄣㄕˋㄇㄚ）以中文注音符为基础展开
    //中文注音符以特定的符号来标记声韵母，更符合汉字的拼读方式，相较于采用拉丁字母作为原料的汉语拼音与英文字母，表达同样的功能可以更少的敲击键盘
    //而采用汉字编码由于汉语体系过于繁杂，西方开发者存在上手困难的问题，因此晓萌光标准算法语言将采用中文注音符作为编码原料
    //由于原键盘键值会作为中文注音符录入，因此晓萌光标准算法原生并不支持拉丁字母的录入，但可以将注音程式码转换为旧时代的联合锐或爪哇等语言
    //另一方面，晓萌光标准算法语言作为一款酝酿中的次时代语言，以中文注音符优化拉丁字母程式码的不足，也利于进一步提升中华文化的国际影响力
    //欢梦橡加密作为爱洁羊第三代加密技术，所采用的联合锐注音程式码，正是晓萌光标准算法语言的前生
    //主题协作器鸿蒙版计划作为开源项目，并支持全球化语言能力，因此本项目暂时使用英文编码，但本项目不会过多的应用爱洁羊特殊智慧能力
    public static PixelMap CropImage(PixelMap mPixelMap,boolean SimpleMode)
    {
        try
        {
            System.gc();
            PixelMap pxm = mPixelMap;
            ImageInfo mImageInfo = pxm.getImageInfo();
            int mWidth = mImageInfo.size.width;
            int mHeight = mImageInfo.size.height;
            int minPixel = Math.min(mWidth, mHeight);
            boolean isResizeMode = minPixel>180&&SimpleMode;
            if(isResizeMode)
            {
                pxm = ResizeImage(mPixelMap,180);
                mImageInfo = pxm.getImageInfo();
                mWidth = mImageInfo.size.width;
                mHeight = mImageInfo.size.height;
            }
            //计算边框单行或单列的最大噪点容错量
            int dx = (int)(mWidth*0.24f+0.5f);
            int dy = (int)(mHeight*0.24f+0.5f);
            //计算边框的最小扫描行数与列数
            int dw = (int)(mWidth*0.12f+0.5f);
            int dh = (int)(mHeight*0.12f+0.5f);
            //计算边框的最大容错行数与列数
            float eRate = 0.15f;
            //判断像素边框的相对颜色，预设值为左上角的顶点像素
            int mColor = pxm.readPixel(new Position(0,0));
            //录入相似颜色的色度、浓度、亮度容差值
            float dValue_H=12f,dValue_S=14f,dValue_V=9f;
            int ErrorPixel;
            boolean[] HorizontalLine_Error = new boolean[mHeight];
            //计算上边框尺寸
            int ErrorLine_TopHorizontal = 0;
            int BorderTop = -1;
            for(int h = 0; h < mHeight; h++)
            {
                ErrorPixel = 0;
                for(int w = 0; w < mWidth; w++)
                {
                    if(!ColorManager.isSimilarColor(pxm.readPixel(new Position(w,h)),mColor,dValue_H,dValue_S,dValue_V))
                        ErrorPixel+=1;
                }
                if(ErrorPixel>dx)
                {
                    ErrorLine_TopHorizontal+=1;
                    HorizontalLine_Error[h] = true;
                }else
                {
                    HorizontalLine_Error[h] = false;
                }

                if((h+1)>dh && ErrorLine_TopHorizontal >= (h+1)*eRate)
                {
                    int num = 0;
                    for(int i = h;i >= 0;i--)
                    {
                        if(HorizontalLine_Error[i])
                        {
                            num++;
                        }else
                        {
                            break;
                        }
                    }
                    BorderTop = (h+1-num);
                    break;
                }
            }
            //计算下边框尺寸
            int ErrorLine_BottomHorizontal = 0;
            int BorderBottom = -1;
            for(int h = (mHeight-1); h >= 0; h--)
            {
                ErrorPixel = 0;
                for(int w = 0; w < mWidth; w++)
                {
                    if(!ColorManager.isSimilarColor(pxm.readPixel(new Position(w,h)),mColor,dValue_H,dValue_S,dValue_V))
                        ErrorPixel+=1;
                }
                if(ErrorPixel>dx)
                {
                    ErrorLine_BottomHorizontal+=1;
                    HorizontalLine_Error[h] = true;
                }else
                {
                    HorizontalLine_Error[h] = false;
                }

                if((mHeight-h)>dh && ErrorLine_BottomHorizontal >= (mHeight-h)*eRate)
                {
                    int num = 0;
                    for(int i = h;i < mHeight;i++)
                    {
                        if(HorizontalLine_Error[i])
                        {
                            num++;
                        }else
                        {
                            break;
                        }
                    }
                    BorderBottom = (mHeight-h-num);
                    break;
                }
            }
            boolean[] VerticalLine_Error = new boolean[mWidth];
            //计算左边框尺寸
            int ErrorLine_LeftVertical = 0;
            int BorderLeft = -1;
            for(int w = 0; w < mWidth; w++)
            {
                ErrorPixel = 0;
                for(int h = 0; h < mHeight; h++)
                {
                    if(!ColorManager.isSimilarColor(pxm.readPixel(new Position(w,h)),mColor,dValue_H,dValue_S,dValue_V))
                        ErrorPixel+=1;
                }
                if(ErrorPixel>dy)
                {
                    ErrorLine_LeftVertical+=1;
                    VerticalLine_Error[w] = true;
                }else
                {
                    VerticalLine_Error[w] = false;
                }

                if((w+1)>dw && ErrorLine_LeftVertical >= (w+1)*eRate)
                {
                    int num = 0;
                    for(int i = w;i >= 0;i--)
                    {
                        if(VerticalLine_Error[i])
                        {
                            num++;
                        }else
                        {
                            break;
                        }
                    }
                    BorderLeft = (w+1-num);
                    break;
                }
            }
            //计算右边框尺寸
            int ErrorLine_RightVertical = 0;
            int BorderRight = -1;
            for(int w = (mWidth-1); w >= 0; w--)
            {
                ErrorPixel = 0;
                for(int h = 0; h < mHeight; h++)
                {
                    if(!ColorManager.isSimilarColor(pxm.readPixel(new Position(w,h)),mColor,dValue_H,dValue_S,dValue_V))
                        ErrorPixel+=1;
                }
                if(ErrorPixel>dy)
                {
                    ErrorLine_RightVertical+=1;
                    VerticalLine_Error[w] = true;
                }else
                {
                    VerticalLine_Error[w] = false;
                }

                if((mWidth-w)>dw && ErrorLine_RightVertical >= (mWidth-w)*eRate)
                {
                    int num = 0;
                    for(int i = w;i < mWidth;i++)
                    {
                        if(VerticalLine_Error[i])
                        {
                            num++;
                        }else
                        {
                            break;
                        }
                    }
                    BorderRight = (mWidth-w-num);
                    break;
                }
            }
            System.gc();
            //当边框无须裁剪时，进入色彩复杂度分析模式，筹划新一轮的裁剪
            if(BorderTop<=0&&BorderBottom<=0&&BorderLeft<=0&&BorderRight<=0)
            {
                int LeftWidth = (int)((mWidth/2f)+0.5f);
                int RightWidth = mWidth-LeftWidth;
                int TopHeight = (int)((mHeight/2f)+0.5f);
                int BottomHeight = mHeight-TopHeight;
                //开始扫描左上角色块
                int avgColor = pxm.readPixel(new Position(0,0));
                int currentColor;
                ErrorPixel = 0;
                for(int h = 0;h < TopHeight;h++)
                {
                    for(int w = 0;w < LeftWidth;w++)
                    {
                        currentColor = pxm.readPixel(new Position(w,h));
                        avgColor = ColorManager.getAverageColor(avgColor,currentColor);
                        if(!ColorManager.isSimilarColor(currentColor,avgColor,dValue_H,dValue_S,dValue_V))
                            ErrorPixel++;
                    }
                }
                float Colorful_TopLeft = ((float)ErrorPixel)/(LeftWidth*TopHeight);
                //开始扫描右上角色块
                avgColor = pxm.readPixel(new Position(LeftWidth,0));
                ErrorPixel = 0;
                for(int h = 0;h < TopHeight;h++)
                {
                    for(int w = LeftWidth;w < mWidth;w++)
                    {
                        currentColor = pxm.readPixel(new Position(w,h));
                        avgColor = ColorManager.getAverageColor(avgColor,currentColor);
                        if(!ColorManager.isSimilarColor(currentColor,avgColor,dValue_H,dValue_S,dValue_V))
                            ErrorPixel++;
                    }
                }
                float Colorful_TopRight = ((float)ErrorPixel)/(RightWidth*TopHeight);
                //开始扫描左下角色块
                avgColor = pxm.readPixel(new Position(0,TopHeight));
                ErrorPixel = 0;
                for(int h = TopHeight;h < mHeight;h++)
                {
                    for(int w = 0;w < LeftWidth;w++)
                    {
                        currentColor = pxm.readPixel(new Position(w,h));
                        avgColor = ColorManager.getAverageColor(avgColor,currentColor);
                        if(!ColorManager.isSimilarColor(currentColor,avgColor,dValue_H,dValue_S,dValue_V))
                            ErrorPixel++;
                    }
                }
                float Colorful_BottomLeft = ((float)ErrorPixel)/(LeftWidth*BottomHeight);
                //开始扫描右下角色块
                avgColor = pxm.readPixel(new Position(LeftWidth,TopHeight));
                ErrorPixel = 0;
                for(int h = TopHeight;h < mHeight;h++)
                {
                    for(int w = LeftWidth;w < mWidth;w++)
                    {
                        currentColor = pxm.readPixel(new Position(w,h));
                        avgColor = ColorManager.getAverageColor(avgColor,currentColor);
                        if(!ColorManager.isSimilarColor(currentColor,avgColor,dValue_H,dValue_S,dValue_V))
                            ErrorPixel++;
                    }
                }
                float Colorful_BottomRight = ((float)ErrorPixel)/(RightWidth*BottomHeight);
                //开始扫描中央区色块
                int point_HorizontalLeft = (int)(mWidth*0.2f);
                int point_HorizontalRight = mWidth-(int)(mWidth*0.2f);
                int point_VerticalTop = (int)(mHeight*0.2f);
                int point_VerticalBottom = mHeight-(int)(mHeight*0.2f);
                avgColor = pxm.readPixel(new Position(point_HorizontalLeft,point_VerticalTop));
                ErrorPixel = 0;
                for(int h = point_VerticalTop;h < point_VerticalBottom;h++)
                {
                    for(int w = point_HorizontalLeft;w < point_HorizontalRight;w++)
                    {
                        currentColor = pxm.readPixel(new Position(w,h));
                        avgColor = ColorManager.getAverageColor(avgColor,currentColor);
                        if(!ColorManager.isSimilarColor(currentColor,avgColor,dValue_H,dValue_S,dValue_V))
                            ErrorPixel++;
                    }
                }
                float Colorful_Center = ((float)ErrorPixel)/((point_HorizontalRight-point_HorizontalLeft)*(point_VerticalBottom-point_VerticalTop));
                float maxColorful = Colorful_TopLeft;
                if(Colorful_TopRight>maxColorful)maxColorful=Colorful_TopRight;
                if(Colorful_BottomLeft>maxColorful)maxColorful = Colorful_BottomLeft;
                if(Colorful_BottomRight>maxColorful)maxColorful = Colorful_BottomRight;
                int HorizontalOffset;
                int VerticalOffset;
                if(Colorful_Center < maxColorful)
                {
                    if(Colorful_TopLeft == maxColorful)
                    {
                        BorderLeft = (int)(LeftWidth/8f);
                        BorderRight = (int)(RightWidth*3f/5f);
                        BorderTop = (int)(TopHeight/6f);
                        BorderBottom = (int)(BottomHeight*37f/70f);
                        HorizontalOffset = (int)(BorderLeft*((Colorful_TopLeft-Colorful_TopRight)/Colorful_TopLeft));
                        VerticalOffset = (int)(BorderTop*((Colorful_TopLeft-Colorful_BottomLeft)/Colorful_TopLeft));
                        BorderLeft -= HorizontalOffset;
                        BorderRight += HorizontalOffset;
                        BorderTop -= VerticalOffset;
                        BorderBottom += VerticalOffset;
                    }else if(Colorful_TopRight == maxColorful)
                    {
                        BorderLeft = (int)(LeftWidth*3f/5f);
                        BorderRight = (int)(RightWidth/8f);
                        BorderTop = (int)(TopHeight/6f);
                        BorderBottom = (int)(BottomHeight*37f/70f);
                        HorizontalOffset = (int)(BorderRight*((Colorful_TopRight-Colorful_TopLeft)/Colorful_TopRight));
                        VerticalOffset = (int)(BorderTop*((Colorful_TopRight-Colorful_BottomRight)/Colorful_TopRight));
                        BorderLeft += HorizontalOffset;
                        BorderRight -= HorizontalOffset;
                        BorderTop -= VerticalOffset;
                        BorderBottom += VerticalOffset;
                    }else if(Colorful_BottomLeft == maxColorful)
                    {
                        BorderLeft = (int)(LeftWidth/8f);
                        BorderRight = (int)(RightWidth*3f/5f);
                        BorderTop = (int)(TopHeight*37f/70f);
                        BorderBottom = (int)(BottomHeight/6f);
                        HorizontalOffset = (int)(BorderLeft*((Colorful_BottomLeft-Colorful_BottomRight)/Colorful_BottomLeft));
                        VerticalOffset = (int)(BorderBottom*((Colorful_BottomLeft-Colorful_TopLeft)/Colorful_BottomLeft));
                        BorderLeft -= HorizontalOffset;
                        BorderRight += HorizontalOffset;
                        BorderTop += VerticalOffset;
                        BorderBottom -= VerticalOffset;
                    }else if(Colorful_BottomRight == maxColorful)
                    {
                        BorderLeft = (int)(LeftWidth*3f/5f);
                        BorderRight = (int)(RightWidth/8f);
                        BorderTop = (int)(TopHeight*37f/70f);
                        BorderBottom = (int)(BottomHeight/6f);
                        HorizontalOffset = (int)(BorderRight*((Colorful_BottomRight-Colorful_BottomLeft)/Colorful_BottomRight));
                        VerticalOffset = (int)(BorderBottom*((Colorful_BottomRight-Colorful_TopRight)/Colorful_BottomRight));
                        BorderLeft += HorizontalOffset;
                        BorderRight -= HorizontalOffset;
                        BorderTop += VerticalOffset;
                        BorderBottom -= VerticalOffset;
                    }
                }
                else
                {
                    BorderLeft = (int)(mWidth*0.14f);
                    BorderRight = (int)(mWidth*0.14f);
                    BorderTop = (int)(mHeight*0.14f);
                    BorderBottom = (int)(mHeight*0.14f);
                    if(Colorful_TopLeft == maxColorful)
                    {
                        HorizontalOffset = (int)(BorderLeft*((Colorful_TopLeft-Colorful_TopRight)*0.33f/Colorful_TopLeft));
                        VerticalOffset = (int)(BorderTop*((Colorful_TopLeft-Colorful_BottomLeft)*0.42f/Colorful_TopLeft));
                        BorderLeft -= HorizontalOffset;
                        BorderRight += HorizontalOffset;
                        BorderTop -= VerticalOffset;
                        BorderBottom += VerticalOffset;
                    }else if(Colorful_TopRight == maxColorful)
                    {
                        HorizontalOffset = (int)(BorderRight*((Colorful_TopRight-Colorful_TopLeft)*0.33f/Colorful_TopRight));
                        VerticalOffset = (int)(BorderTop*((Colorful_TopRight-Colorful_BottomRight)*0.42f/Colorful_TopRight));
                        BorderLeft += HorizontalOffset;
                        BorderRight -= HorizontalOffset;
                        BorderTop -= VerticalOffset;
                        BorderBottom += VerticalOffset;
                    }else if(Colorful_BottomLeft == maxColorful)
                    {
                        HorizontalOffset = (int)(BorderLeft*((Colorful_BottomLeft-Colorful_BottomRight)*0.33f/Colorful_BottomLeft));
                        VerticalOffset = (int)(BorderBottom*((Colorful_BottomLeft-Colorful_TopLeft)*0.42f/Colorful_BottomLeft));
                        BorderLeft -= HorizontalOffset;
                        BorderRight += HorizontalOffset;
                        BorderTop += VerticalOffset;
                        BorderBottom -= VerticalOffset;
                    }else if(Colorful_BottomRight == maxColorful)
                    {
                        HorizontalOffset = (int)(BorderRight*((Colorful_BottomRight-Colorful_BottomLeft)*0.33f/Colorful_BottomRight));
                        VerticalOffset = (int)(BorderBottom*((Colorful_BottomRight-Colorful_TopRight)*0.42f/Colorful_BottomRight));
                        BorderLeft += HorizontalOffset;
                        BorderRight -= HorizontalOffset;
                        BorderTop += VerticalOffset;
                        BorderBottom -= VerticalOffset;
                    }
                }
            }
            if(isResizeMode)
            {
                BorderLeft = (int)((BorderLeft*minPixel/180f)+0.5f);
                BorderRight = (int)((BorderRight*minPixel/180f)+0.5f);
                BorderTop = (int)((BorderTop*minPixel/180f)+0.5f);
                BorderBottom = (int)((BorderBottom*minPixel/180f)+0.5f);
                pxm = mPixelMap;
                mImageInfo = pxm.getImageInfo();
                mWidth = mImageInfo.size.width;
                mHeight = mImageInfo.size.height;
            }
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            int nWidth = mWidth-BorderLeft-BorderRight;
            int nHeight = mHeight-BorderTop-BorderBottom;
            initializationOptions.size = new Size(nWidth,nHeight);
            initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
            initializationOptions.editable = true;
            PixelMap nPixelMap = PixelMap.create(initializationOptions);
            for(int h = 0; h < nHeight; h++)
            {
                for(int w = 0; w < nWidth; w++)
                {
                    nPixelMap.writePixel(new Position(w,h),pxm.readPixel(new Position(w+BorderLeft,h+BorderTop)));
                }
            }
            return nPixelMap;
        }
        catch(Exception ex)
        {
            return mPixelMap;
        }
    }

    public static PixelMap ColorfulImage(PixelMap mPixelMap,boolean SimpleMode)
    {
        try
        {
            System.gc();
            ImageInfo mImageInfo = mPixelMap.getImageInfo();
            int mWidth = mImageInfo.size.width;
            int mHeight = mImageInfo.size.height;
            if((Math.min(mWidth, mHeight))>180&&SimpleMode)
                ColorManager.Init(ResizeImage(mPixelMap,180));
            else
                ColorManager.Init(mPixelMap);
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            initializationOptions.size = new Size(mWidth,mHeight);
            initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
            initializationOptions.editable = true;
            PixelMap nPixelMap = PixelMap.create(initializationOptions);
            for(int h = 0; h < mHeight; h++)
            {
                for(int w = 0; w < mWidth; w++)
                {
                    nPixelMap.writePixel(new Position(w,h),ColorManager.getFixedColor(mPixelMap.readPixel(new Position(w,h))));
                }
            }
            return nPixelMap;
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            return mPixelMap;
        }
    }

    public static boolean isDarkImage(PixelMap mPixelMap)
    {
        try
        {
            System.gc();
            PixelMap pixelMap = ResizeImage(mPixelMap, 30);
            ImageInfo mImageInfo = pixelMap.getImageInfo();
            int mWidth = mImageInfo.size.width;
            int mHeight = mImageInfo.size.height;
            int DarkAmount = 0;
            for (int h = 0; h < mHeight; h++)
            {
                for (int w = 0; w < mWidth; w++)
                {
                    if(ColorManager.getHsvBox(pixelMap.readPixel(new Position(w, h))).getValue()<=42f)
                        DarkAmount++;
                }
            }
            return (((float)DarkAmount)/(mHeight*mHeight))>0.32f;
        }catch (Exception e) { return true;}
    }

    public static PixelMap ObtainImage(Uri uri,Context mContext)
    {
        DataAbilityHelper dataAbilityHelper = GeneralUtil.createDataAbilityHelper(mContext);
        ImageSource imageSource;
        PixelMap pxm;
        try
        {
            FileDescriptor fd = dataAbilityHelper.openFile(uri, "r");
            imageSource = ImageSource.create(fd, null);
            pxm = imageSource.createPixelmap(null);
        } catch (Exception e) {pxm = null;}
        return pxm;
    }

    public static PixelMap ResizeImage(PixelMap mPixelMap,int Quality)
    {
        ImageInfo mImageInfo = mPixelMap.getImageInfo();
        int mWidth = mImageInfo.size.width;
        int mHeight = mImageInfo.size.height;
        int nWidth;
        int nHeight;
        if(mWidth>mHeight)
        {
            nWidth = mWidth*Quality/mHeight;
            nHeight = Quality;
        }
        else
        {
            nWidth = Quality;
            nHeight = mHeight*Quality/mWidth;
        }
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(nWidth,nHeight);
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        initializationOptions.scaleMode = ScaleMode.FIT_TARGET_SIZE;
        initializationOptions.editable = true;
        return PixelMap.create(mPixelMap,initializationOptions);
    }

    public static PixelMap ResizeImage(PixelMap mPixelMap,int w,int h)
    {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(w,h);
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        initializationOptions.scaleMode = ScaleMode.CENTER_CROP;
        initializationOptions.editable = true;
        return PixelMap.create(mPixelMap,initializationOptions);
    }

    public static void saveImage(Context context,Uri targetUri, String fileName)
    {
        System.gc();
        try
        {
            DataAbilityHelper dataAbilityHelper = GeneralUtil.createDataAbilityHelper(context);
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try
            {
                inputStream = new FileInputStream(dataAbilityHelper.openFile(targetUri, "r"));
                outputStream = new FileOutputStream(fileName);
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) > 0)
                    outputStream.write(buffer, 0, length);
                outputStream.flush();
                outputStream.close();
            }catch (Exception ex) { ex.printStackTrace();}
            finally
            {
                try
                {
                    if (outputStream != null)
                        outputStream.close();
                    if (inputStream != null)
                        inputStream.close();
                } catch (IOException e) {e.printStackTrace();}
            }
        }catch (Exception e){e.printStackTrace();}
    }

    public static void saveImage(String fileName, PixelMap pixelMap)
    {
        System.gc();
        try
        {
            ImagePacker imagePacker = ImagePacker.create();
            ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
            OutputStream outputStream = new FileOutputStream(fileName);
            packingOptions.format = "image/jpeg";
            packingOptions.quality = 100;
            boolean result = imagePacker.initializePacking(outputStream, packingOptions);
            if (result)
            {
                result = imagePacker.addImage(pixelMap);
                if (result)
                {
                    imagePacker.finalizePacking();
                }
            }
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {e.printStackTrace();}
    }

    public static FileDescriptor saveImage(String fileName, PixelMap pixelMap,String path,Context mContext) throws Exception
    {
        ValuesBucket valuesBucket = new ValuesBucket();
        valuesBucket.putString(AVStorage.Images.Media.DISPLAY_NAME, fileName);
        valuesBucket.putString("relative_path", path);
        valuesBucket.putString(AVStorage.Images.Media.MIME_TYPE, "image/jpeg");
        valuesBucket.putInteger("is_pending", 1);
        DataAbilityHelper helper = GeneralUtil.createDataAbilityHelper(mContext);
        int id = helper.insert(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, valuesBucket);
        Uri uri = Uri.appendEncodedPathToUri(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, String.valueOf(id));
        FileDescriptor fd = helper.openFile(uri, "w");
        ImagePacker imagePacker = ImagePacker.create();
        ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
        OutputStream outputStream = new FileOutputStream(fd);
        packingOptions.format = "image/jpeg";
        packingOptions.quality = 100;
        boolean result = imagePacker.initializePacking(outputStream, packingOptions);
        if (result)
        {
            result = imagePacker.addImage(pixelMap);
            if (result)
            {
                imagePacker.finalizePacking();
            }
        }
        outputStream.flush();
        outputStream.close();
        valuesBucket.clear();
        valuesBucket.putInteger("is_pending", 0);
        helper.update(uri, valuesBucket, null);
        return fd;
    }

    public static void saveImage(String fileName, PixelMap pixelMap,Context mContext,String Toast_Image_SaveFinish,String Toast_Image_SaveFailed)
    {
        System.gc();
        try
        {
            saveImage(fileName, pixelMap,"DCIM/ImageIntelligence/", mContext);
            new GeneralToast(mContext)
                    .setText(Toast_Image_SaveFinish+"DCIM/ImageIntelligence/"+fileName+".jpg")
                    .show();
        } catch (Exception e)
        {
            new GeneralToast(mContext)
                    .setText(Toast_Image_SaveFailed)
                    .show();
        }
    }
}
